﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using EONFULLSIN2.Core;
using NModbus.Device;
using NModbus;

namespace EONFULLSIN2.Services.Device
{
    public abstract class ModbusBaseServices : IModbusBaseServices
    {
        protected TcpClient _tcpClient;
        protected IModbusMaster _master;

        /// <summary>
        /// 交给子类赋值
        /// </summary>
        public abstract string IpAddress { protected set; get; }

        /// <summary>
        /// 交给子类赋值
        /// </summary>
        public virtual int Port { protected set; get; }

        public bool IsConnect { private set; get; }

        public async Task<bool> ConnectAsync()
        {
            try {

                if (_tcpClient == null || !_tcpClient.Connected) {

                    _tcpClient = new TcpClient();
                    await _tcpClient.ConnectAsync(IPAddress.Parse(IpAddress), Port);
                    ModbusFactory factory = new ModbusFactory();
                    _master = factory.CreateMaster(_tcpClient);
                    _master.Transport.WriteTimeout = 2000;
                    _master.Transport.ReadTimeout = 2000;
                    _master.Transport.WaitToRetryMilliseconds = 500;
                    _master.Transport.Retries = 3;
                    IsConnect = _tcpClient.Connected;
                }

                return _tcpClient.Connected;
            } catch (Exception ex) {
                IsConnect = false;
                LogManager.Error(ex);
                throw new InvalidOperationException($"{IpAddress}:{Port},{ex.Message}", ex);
            }
            //return false;
        }

        public Task<bool> DisConnectAsync()
        {
            try
            {
                if (_tcpClient != null && _tcpClient.Connected)
                {
                    _tcpClient.Close();
                }
                _master = null;
                IsConnect = false;
                return Task.FromResult(true);
            }
            catch (Exception ex)
            {
                //LogManager.Error(ex);
                throw new InvalidOperationException($"{IpAddress}:{Port},{ex.Message}", ex);
            }
        }

        public Task<ushort[]> ReadInputRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints)
        {
            try
            {
                if (_tcpClient != null && _tcpClient.Connected)
                {
                    return _master.ReadInputRegistersAsync(slaveAddress, startAddress, numberOfPoints);
                }
                else {
                    throw new Exception($"{IpAddress}:{Port},is not connect");
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"{IpAddress}:{Port},{ex.Message}", ex);
            }
           
            //return Task.FromResult(Array.Empty<ushort>());
        }

        public Task<ushort[]> ReadHoldingRegistersAsync(byte slaveAddress, ushort startAddress, ushort numberOfPoints)
        {
            try
            {
                if (_tcpClient != null && _tcpClient.Connected)
                {
                    return _master.ReadHoldingRegistersAsync(slaveAddress, startAddress, numberOfPoints);
                }
                else {
                    throw new Exception($"{IpAddress}:{Port},is not connect");
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"{IpAddress}:{Port},{ex.Message}", ex);
            }
            //return Task.FromResult(Array.Empty<ushort>());
        }

    }
}
